package com.sokobanboxpro.game.system;

import com.sokobanboxpro.game.exception.ConfigFileExeption;
import com.sokobanboxpro.game.exception.ConfigValueNotFoundException;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * Загрузка конфигурации из файла
 * 
 * Запись в конфигурационом файле имеет вид "имя=значение" Поддерживаютсься
 * коменатрии, которые начинаются на # Пустые строки игнорируются Для каждого
 * типа данных создана своя функция. В качесте аргумента передается имя
 * значение, которые надо получить Для записи булевых значений используте
 * строки, true и false Функция для загрузки значений load();
 * 
 * @author Esr 
 * @copyright 2012 Esr 
 * @date 21.01.2012
 */
public class Config {

		/**
		 * @brief Массив значений, загруженных из файла
		 */
		private static List<String[]> configs = null;

		/**
		 * Функция проходит все значения, находящиеся в массиве, и находит нужное
		 * @brief Получить значение из массива
		 *
		 * @param value Имя значения, которое ищется
		 * @return Значение записи, если имя не найдено - null
		 */
		private static String value(String value) throws ConfigValueNotFoundException {

				for (int i = 0; i < configs.size(); i++) {
						String[] val = configs.get(i);
						if (val[0].equals(value)) {
								return val[1];
						}

				}
				throw new ConfigValueNotFoundException(value);
		}

		/**
		 * Для преобразование из строки используется Integer.parseInt @brief
		 * Получает значение в типе int
		 *
		 * @param value Имя значения, которое ищется
		 * @return Значение записи
		 */
		public static int toInt(String value) throws ConfigValueNotFoundException {

				return Integer.parseInt(value(value));

		}

		/**
		 * @brief Получить значение в типе String
		 *
		 * @param value Имя значения, которое ищется
		 * @return Значение записи
		 */
		public static String toStr(String value) throws ConfigValueNotFoundException {

				return value(value);

		}

		/**
		 * Для преобразования используется стравнение строки через equals @brief
		 * Получить значение в типе boolean
		 *
		 * @param value Имя значения, которое ищется
		 * @return Значение записи @note Если в файле записано страка отличная от
		 * true или false, то функция возращает false
		 */
		public static boolean toBool(String value) throws ConfigValueNotFoundException {

				if (value(value).equals("true")) {
						return true;
				} else {
						return false;
				}

		}

		/**
		 *
		 * @brief Чтение файла, и загрузка значений в массив
		 *
		 * @param fileName Путь до файла
		 * @param fromJar Загружается ли файл из jar. true - да, false - нет
		 */
		private static void loadFromFile(String fileName, boolean fromJar) throws ConfigFileExeption {

				List<String[]> configs = new ArrayList<String[]>();

				try {

						BufferedReader reader;

						if (fromJar) {

								InputStream inStream = Config.class.getResourceAsStream(fileName);
								reader = new BufferedReader(new InputStreamReader(inStream));

						} else {

								reader = new BufferedReader(new FileReader(fileName));

						}

						String line;

						while ((line = reader.readLine()) != null) {

								if (!(line.trim().isEmpty() || line.trim().charAt(0) == '#')) {
										String[] value = line.split("=");
										configs.add(value);

								}

						}

				} catch (FileNotFoundException e) {
						throw new ConfigFileExeption("Файл конфигурации не найден");
				} catch (IOException e) {
						throw new ConfigFileExeption("Ошибка чтения файла конфигурации");
				} catch (Exception e) {
						throw new ConfigFileExeption("Ошибка открытия файла конфигурации");
				}

				Config.configs = configs;

		}

		/**
		 * @param fileName Путь до файла
		 * @param fromJar Загружается ли файл из jar. true - да, false - нет
		 */
		public static void load(String configFile, boolean fromJar) throws ConfigFileExeption {

				loadFromFile(configFile, fromJar);

		}
}
